# 函数是一个带名字的代码块
# 名字：函数名
# 代码块：函数体

# 函数使用
"""
语法:
def 函数名():
    代码块(函数体)

函数名命名规范：
必须符合标识符的命名规范
"""
# 定义了一个名字叫info的函数
a = 'AAAAAAAAAAAAAAAAAAAA'
def info():
    for i in range(5):
        print(a)
## 调用
"""
语法：
函数名()
"""
info()
# TODO 总结函数特点
"""
1. 函数定义的时候不执行，只有在调用的时候才会执行
2. 一次定义多次调用。解决冗余代码和后期扩展维护问题。
3. 函数会把运行结果返回到调用的地方
"""

# 参数
# 解决函数通用性问题
# 定义时的参数叫做形式参数：形参
def add(a, b):
    print(a + b)

# 调用时的参数叫做实际参数：实参
add(1, 2)
add(2, 3)
add(5, 3)
add(10, 20)
# 说明：实参必须和形参一一对应

# 函数的返回值
"""
def 函数名([param1, param2, ...]):
    函数体
    return 函数要返回的结果（表达式）
"""
"""
说明：
1. 返回函数的运行结果
2. return后的代码不执行
"""
# 函数定义三部曲
"""
1. 函数名
2. 确定形参
3. 确定函数返回值
"""

# pass语句
# 代码块占位符
# 分支语句、循环、函数
def fn():
    pass

# 函数说明文档，也就是函数注释的标准写法
"""
语法：
def fn():
    '''
    函数的注释
    '''
    函数体
说明：
写在函数的最上面
"""
def add(a, b):
    """
    求2个数的和（函数功能描述）
    :param a: int 数字1
    :param b: int 数字2
    :return: int 2个数的和
    """
    return a + b
# help()
# 获取函数的说明文档
help(add)
help(print)

# 函数参数一共有以下几种：
# 函数定义时的叫法
"""
1. 必填参数
2. 默认参数
3. 不定长参数
"""

# 必填参数（必须参数）
# 说明：必填参数，在函数调用的时候，必须传入实参。

def add(a, b):
    return a + b


add(1, 2)

# 默认参数
# 说明：就是形参有默认值，可以不用传入实参
# 定义
def stu_info(name, age, class_name='1205'):
    print(name, age, class_name)

# 不定长参数
# 说明：不定长这样的形参可以传入任意多个实参
# 位置不定长参数
# 说明：
"""
函数调用时可以传入任意多个位置参数,打包为一个元组（args）
"""
# 定义
def fn1(*args):
    print(args)

# 调用
fn1('a', 1, 2, 'hello', True)

# 关键字不定长参数
# 函数调用时可以传入任意多个关键字实参,打包为一个字典
# 定义
def fn2(**kwargs):
    print(kwargs)
# 调用
fn2(a=1, b=2, c='hello', name='tt', age=19)
print('==' * 20)

# 位置不定长和关键字不定长一起使用
def fn3(*args, **kwargs):
    print(args)
    print(kwargs)

fn3(1, 2, 3, a=100, b=200, c=300)

# 实参的两种传递形式
# 两种方式没有优劣之分，都可以使用
"""
1. 位置传参
2. 关键字传参
"""

# 位置传参
# 说明：按照形参的顺序传入实参

# 定义
def info(name, age, addr):
    print(name, age, addr)

# 调用
info('hello', 18, '成都')

# 关键字传参
# 说明：按照形参的名字传入实参。关键字传参和传入实参的顺序没有关系，只和形参名字有关系。

# 定义
def info(name, age, addr):
    print(name, age, addr)
# 调用
info(age=18, name='zs', addr='重庆')

# 必填参数，位置不定长，默认参数，关键字不定长
def fn(a, b, *args, m=100, **kwargs):
    print(a, b)
    print(args)
    print(m)
    print(kwargs)

fn(1, 2, 100, 200)
print('==' * 20)

fn(1, 2, 100, 200, x='x', y='y')
print('==' * 20)

fn(1, 2, 100, 200, m=1000, x='x', y='y')
print('==' * 20)

print(1, 2, 3, ' ')